package poker;
import java.util.Scanner;

/**
 * Klasa  odpowiedzialna za przebieg rozgrywki.
 */
public class Stol {
    /**
     * Konstruktor tworzacy graczy.
     * 
     * @param ludzie imiona ludzi.
     * @param boty imiona botow.
     * @param liczbaLudzi liczba ludzi.
     * @param liczbaBotow liczba botow.
     * @param liczbaZetonow liczba zetonow jednego gracza.
     * @param wysokoscWpisowego wysokosc wpisowego w grze.
     */
    public Stol(final String[] ludzie, final String[] boty, 
            final int liczbaLudzi, final int liczbaBotow, 
            final int liczbaZetonow, final int wysokoscWpisowego) {
        gracze = new Gracz[liczbaLudzi + liczbaBotow];
        zetony = liczbaZetonow * (liczbaLudzi + liczbaBotow);
        wpisowe = wysokoscWpisowego;
        int i = 0;
        for (; i < liczbaLudzi; i++) {
            gracze[i] = new Czlowiek(ludzie[i], liczbaZetonow);
        }
        
        for (; i < liczbaBotow + liczbaLudzi; i++) {
            gracze[i] = new Bot(boty[i], liczbaZetonow);
        }
        talia = new Talia();
    }
    /**
     * Pole przechowujace talie kart.
     */
    private Talia talia;
    /**
     * Tablica przechowujaca graczy.
     */
    private Gracz[] gracze;
    /**
     * tablica przechowujaca karty wykorzystane 
     * w partii celem kontroli oszustwa.
     */
    private boolean[][] zbieraneKarty;
    /**
     * Stala przechowujaca ilosc zetonow w grze.
     */
    private final int zetony;
    /**
     * Stala przechowujaca wysokosc wpisowego.
     */
    private final int wpisowe;
    /**
     * Pole przechowujace aktualna pule.
     */
    private int pula;
    /**
     * Stala przechowujaca maksymalna ilosc kart jednego gracza.
     */
    private static final int ILOSC_KART = 5;
    /**
     * Maksymalna ilosc graczy.
     */
    private static final int MAKS_GRACZY = 4;   
    /**
     * stala przechowujaca ilosc mozliwych figur w talii.
     */
    private static final int ILOSC_FIGUR = 13;   
    /**
     * stala przechowujaca ilosc mozliwych kolorow w talii.
     */
    private static final int ILOSC_KOLOROW = 4; 
    /**
     * Metoda rozdajaca karty gracza.
     */
    private void rozdajKarty() {
        for (int i = 0; i < ILOSC_KART; i++) {
            for (int j = 0; j < gracze.length; j++) {
                gracze[j].wezKarte(talia.wezKarte());
            }
        }
        for (int i = 0; i < gracze.length; i++) {
            gracze[i].sortuj();
        }
    }
    /**
     * Metoda pozwalajaca na wymiane kart przez kolejnych graczy.
     */
    private void wymienKarty() {
        zbieraneKarty = new boolean[ILOSC_FIGUR][ILOSC_KOLOROW];
        Karta[] zwroconeKarty;
        for (int i = 0; i < gracze.length; i++) {
            zwroconeKarty = gracze[i].wymienKarty(talia);
            if (zwroconeKarty != null) {
                for (int j = 0; j < zwroconeKarty.length; j++) {
                    zbieraneKarty[zwroconeKarty[j].pobierzKodFigury() - 2]
                            [zwroconeKarty[j].pobierzKodKoloru()] = true;
                }
            }
            gracze[i].sortuj();
        }
    }
    /**
     * Metoda pozwalajaca wyswietlic na ekran karty wszystkich graczy.
     */
    private void pokazWszystkichKarty() {
        for (int i = 0; i < gracze.length; i++) {
            System.out.println(gracze[i] + " " 
            + SprawdzUklad.jakiUklad(gracze[i].pokazKarty()));
        }
    }
    /**
     * Metoda sprawdzajaca uczciowosc partii.
     * 
     * @return true jesli partia byla uczciwa, false w przeciwnym wypadku.
     */
    private boolean sprawdzUczciwosc() {
        for (int i = 0; i < gracze.length; i++) {
            Karta[] kartyGracza = gracze[i].pokazKarty();
            for (int j = 0; j < kartyGracza.length; j++) {
                zbieraneKarty[kartyGracza[j].pobierzKodFigury() - 2]
                        [kartyGracza[j].pobierzKodKoloru()] = true;
            }
        }
        Karta tmp;
        while ((tmp = talia.wezKarte()) != null) {
            zbieraneKarty[tmp.pobierzKodFigury() - 2][tmp.pobierzKodKoloru()] 
                    = true;
        }
        
        for (int i = 0; i < ILOSC_FIGUR; i++) {
            for (int j = 0; j < ILOSC_KOLOROW; j++) {
                if (!zbieraneKarty[i][j]) {
                    return false;
                }
            }
        }
        return true;
    }
    /**
     * Metoda zwracajaca zwyciezce partii.
     * 
     * @return referencja do zwyciezcy lub null w przypadku remisu
     */
    private Gracz ktoWygral() {
        Gracz najlepszy = gracze[0];
        
        boolean czyRemis = false;
        for (int i = 1; i < gracze.length; i++) {
            if (SprawdzUklad.wartosciUkladu(gracze[i].pokazKarty()) 
                    > SprawdzUklad.wartosciUkladu(najlepszy.pokazKarty())) {   
                najlepszy = gracze[i];
                czyRemis = false;
            } else {
                if (SprawdzUklad.wartosciUkladu(gracze[i].pokazKarty()) 
                       == SprawdzUklad.wartosciUkladu(najlepszy.pokazKarty())) {
                    int wynik = SprawdzUklad.porownajTeSameUklady(
                           najlepszy.pokazKarty(), gracze[i].pokazKarty(), 
                           SprawdzUklad.wartosciUkladu(najlepszy.pokazKarty()));
                    if (wynik == 0) {
                        czyRemis = true;
                    } else {
                        czyRemis = false;
                        if (wynik < 0) {
                            najlepszy = gracze[i]; 
                        }
                    }       
                }
            }
        }
        if (czyRemis) {
            najlepszy = null;
        }
        return najlepszy; 
    }

    /**
     * Metoda odpowiedzialna za przeczytanie liczby graczy stworzenie stolu 
     * i rezyserowanie gry.
     * 
     * @param args argumenty wywolania (nie uzywane)
     */
    public static void main(final String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Podaj liczbe graczy ludzi oraz liczbe botow");
        int liczbaLudzi = sc.nextInt();
        int liczbaBotow = sc.nextInt();
         
        if (liczbaLudzi + liczbaBotow < 2) {
            System.out.println("za malo graczy");
            System.exit(0);
        }
        if (liczbaLudzi + liczbaBotow > MAKS_GRACZY) {
            System.out.println("za duzo graczy");
            System.exit(0);
        }
        String[] imionaLudzi = {"Gracz1", "Gracz2", "Gracz3", "Gracz4"};
        String[] imionaBotow = {"Bot1", "Bot2", "Bot3", "Bot4"};
        Stol stol = new Stol(imionaLudzi, imionaBotow, 
                liczbaLudzi, liczbaBotow, 0, 0);
        stol.rozdajKarty();
        stol.wymienKarty();
        stol.pokazWszystkichKarty();
        if (stol.sprawdzUczciwosc()) {
            Gracz zwyciezca = stol.ktoWygral();
            if (zwyciezca == null) {
                System.out.println("Remis");
            } else {
                System.out.println("wygrywa " + zwyciezca + " ukladem " 
                              + SprawdzUklad.jakiUklad(zwyciezca.pokazKarty()));
            }
        } else {
            System.out.println("wykryto oszustwo!");
        }
        sc.close();   
    }
}